
/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2020原作者。
 *
 *根据Apache许可证2.0版（“许可证”）许可；
 *除非符合许可证的规定，否则您不得使用此文件。
 *您可以在以下网址获取许可证副本
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，否则软件
 *根据许可证分发是在“按原样”的基础上分发的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限的特定语言，请参阅许可证
 *许可证下的限制。
 */

package org.springframework.context.support;

import java.io.IOException;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextException;
import org.springframework.lang.Nullable;

/**
 * Base class for {@link org.springframework.context.ApplicationContext}
 * implementations which are supposed to support multiple calls to {@link #refresh()},
 * creating a new internal bean factory instance every time.
 * Typically (but not necessarily), such a context will be driven by
 * a set of config locations to load bean definitions from.
 *
 * <p>The only method to be implemented by subclasses is {@link #loadBeanDefinitions},
 * which gets invoked on each refresh. A concrete implementation is supposed to load
 * bean definitions into the given
 * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory},
 * typically delegating to one or more specific bean definition readers.
 *
 * <p><b>Note that there is a similar base class for WebApplicationContexts.</b>
 * {@link org.springframework.web.context.support.AbstractRefreshableWebApplicationContext}
 * provides the same subclassing strategy, but additionally pre-implements
 * all context functionality for web environments. There is also a
 * pre-defined way to receive config locations for a web context.
 *
 * <p>Concrete standalone subclasses of this base class, reading in a
 * specific bean definition format, are {@link ClassPathXmlApplicationContext}
 * and {@link FileSystemXmlApplicationContext}, which both derive from the
 * common {@link AbstractXmlApplicationContext} base class;
 * {@link org.springframework.context.annotation.AnnotationConfigApplicationContext}
 * supports {@code @Configuration}-annotated classes as a source of bean definitions.
 *
 * @author Juergen Hoeller
 * @author Chris Beams
 * @since 1.1.3
 * @see #loadBeanDefinitions
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory
 * @see org.springframework.web.context.support.AbstractRefreshableWebApplicationContext
 * @see AbstractXmlApplicationContext
 * @see ClassPathXmlApplicationContext
 * @see FileSystemXmlApplicationContext
 * @see org.springframework.context.annotation.AnnotationConfigApplicationContext
 */
/**
 *｛@link org.springframework.context.ApplicationContext｝的基类
 *应该支持对{@link#refresh（）}的多次调用的实现，
 *每次都创建一个新的内部bean工厂实例。
 *通常（但不一定），这样的上下文将由
 *从中加载bean定义的一组配置位置。
 *
 *<p>子类唯一要实现的方法是{@link#loadBeanDefinitions}，
 *其在每次刷新时被调用。应该加载一个具体的实现
 *给定的bean定义
 *｛@link org.springframework.beans.factory.support.DefaultListableBeanFactory｝，
 *通常委托给一个或多个特定的bean定义读取器。
 *
 *<p><b>请注意，WebApplicationContexts有一个类似的基类</b>
 *｛@link org.springframework.web.context.support.AbstractRefreshableWebApplicationContext｝
 *提供了相同的子类化策略，但额外预实现
 *web环境的所有上下文功能。还有一个
 *接收web上下文的配置位置的预定义方式。
 *
 *<p>这个基类的具体独立子类，读取
 *具体的bean定义格式为｛@link ClassPathXmlApplicationContext｝
 *和｛@link FileSystemXmlApplicationContext｝，它们都派生自
 *公共｛@link AbstractXmlApplicationContext｝基类；
 *｛@link org.springframework.context.annotation.AnnotationConfigApplicationContext｝
 *支持{@code@Configuration}注释类作为bean定义的来源。
 *
 *@作者Juergen Hoeller
 *@作者Chris Beams
 *@自1.1.3起
 *@参见#loadBeanDefinitions
 *@请参阅org.springframework.beans.factory.support.DefaultListableBeanFactory
 *@请参阅org.springframework.web.context.support.AbstractRefreshableWebApplicationContext
 *@请参阅AbstractXmlApplicationContext
 *@参见ClassPathXmlApplicationContext
 *@请参阅文件系统XmlApplicationContext
 *@参见org.springframework.context.annotation.AnnotationConfigApplicationContext
 */
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

	@Nullable
	private Boolean allowBeanDefinitionOverriding;

	@Nullable
	private Boolean allowCircularReferences;

	/** Bean factory for this context. */
	@Nullable
	private volatile DefaultListableBeanFactory beanFactory;


	/**
	 * Create a new AbstractRefreshableApplicationContext with no parent.
	 */
	/** Bean factory for this context. */
	@可为null
	private volatile DefaultListableBeanFactory beanFactory；


	/**
	 *创建一个没有父级的新AbstractRefreshableApplicationContext。
	 */
	public AbstractRefreshableApplicationContext() {
	}

	/**
	 * Create a new AbstractRefreshableApplicationContext with the given parent context.
	 * @param parent the parent context
	 */
	/**
	 *使用给定的父上下文创建一个新的AbstractRefreshableApplicationContext。
	 *@param parent父上下文
	 */
	public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
		super(parent);
	}


	/**
	 * Set whether it should be allowed to override bean definitions by registering
	 * a different definition with the same name, automatically replacing the former.
	 * If not, an exception will be thrown. Default is "true".
	 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
	 */
	/**
	 *设置是否应允许通过注册来覆盖bean定义
	 *具有相同名称的不同定义，自动替换前者。
	 *否则，将引发异常。默认值为“true”。
	 *@见org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverrideing
	 */
	public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
		this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
	}

	/**
	 * Set whether to allow circular references between beans - and automatically
	 * try to resolve them.
	 * <p>Default is "true". Turn this off to throw an exception when encountering
	 * a circular reference, disallowing them completely.
	 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
	 */
	/**
	 *设置是否允许bean之间的循环引用-以及自动
	 *试着解决它们。
	 *<p>默认值为“true”。关闭此选项可在遇到异常时引发异常
	 *循环引用，完全禁止它们。
	 *请参阅org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
	 */
	public void setAllowCircularReferences(boolean allowCircularReferences) {
		this.allowCircularReferences = allowCircularReferences;
	}


	/**
	 * This implementation performs an actual refresh of this context's underlying
	 * bean factory, shutting down the previous bean factory (if any) and
	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
	 */
	/**
	 *此实现执行此上下文的底层的实际刷新
	 *bean工厂，关闭以前的bean工厂（如果有的话），并且
	 *为上下文生命周期的下一阶段初始化一个新的bean工厂。
	 */
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

	@Override
	protected void cancelRefresh(BeansException ex) {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory != null) {
			beanFactory.setSerializationId(null);
		}
		super.cancelRefresh(ex);
	}

	@Override
	protected final void closeBeanFactory() {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory != null) {
			beanFactory.setSerializationId(null);
			this.beanFactory = null;
		}
	}

	/**
	 * Determine whether this context currently holds a bean factory,
	 * i.e. has been refreshed at least once and not been closed yet.
	 */
	/**
	 *确定此上下文当前是否包含一个bean工厂，
	 *即已经被刷新至少一次并且还没有被关闭。
	 */
	protected final boolean hasBeanFactory() {
		return (this.beanFactory != null);
	}

	@Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory == null) {
			throw new IllegalStateException("BeanFactory not initialized or already closed - " +
					"call 'refresh' before accessing beans via the ApplicationContext");
		}
		return beanFactory;
	}

	/**
	 * Overridden to turn it into a no-op: With AbstractRefreshableApplicationContext,
	 * {@link #getBeanFactory()} serves a strong assertion for an active context anyway.
	 */
	/**
	 *重写以将其变成非操作：使用AbstractRefreshableApplicationContext，
	 *{@link#getBeanFactory（）}为活动上下文提供了一个强断言。
	 */
	@Override
	protected void assertBeanFactoryActive() {
	}

	/**
	 * Create an internal bean factory for this context.
	 * Called for each {@link #refresh()} attempt.
	 * <p>The default implementation creates a
	 * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
	 * with the {@linkplain #getInternalParentBeanFactory() internal bean factory} of this
	 * context's parent as parent bean factory. Can be overridden in subclasses,
	 * for example to customize DefaultListableBeanFactory's settings.
	 * @return the bean factory for this context
	 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
	 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading
	 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
	 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
	 */
	/**
	 *为此上下文创建一个内部bean工厂。
	 *为每一次{@link#refresh（）}尝试调用。
	 *＜p＞默认实现创建
	 *｛@link org.springframework.beans.factory.support.DefaultListableBeanFactory｝
	 *使用此的{@linkplain#getInternalParentBeanFactory（）内部bean工厂}
	 *上下文的父级作为父bean工厂。可以在子类中重写，
	 *例如，自定义DefaultListableBeanFactory的设置。
	 *@返回此上下文的bean工厂
	 *@见org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverrideing
	 *请参阅org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagleClassLoading
	 *请参阅org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
	 *@see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDessiteWrapping
	 */
	protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}

	/**
	 * Customize the internal bean factory used by this context.
	 * Called for each {@link #refresh()} attempt.
	 * <p>The default implementation applies this context's
	 * {@linkplain #setAllowBeanDefinitionOverriding "allowBeanDefinitionOverriding"}
	 * and {@linkplain #setAllowCircularReferences "allowCircularReferences"} settings,
	 * if specified. Can be overridden in subclasses to customize any of
	 * {@link DefaultListableBeanFactory}'s settings.
	 * @param beanFactory the newly created bean factory for this context
	 * @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
	 * @see DefaultListableBeanFactory#setAllowCircularReferences
	 * @see DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
	 * @see DefaultListableBeanFactory#setAllowEagerClassLoading
	 */
	/**
	 *自定义此上下文使用的内部bean工厂。
	 *为每一次{@link#refresh（）}尝试调用。
	 *＜p＞默认实现应用此上下文的
	 *｛@linkplain#setAllowBeanDefinitionOverrideing“allowBeanDefinitionOverriding”｝
	 *和{@linkplain#setAllowCircularReferences“allowCircularReferences”}设置，
	 *如果指定的话。可以在子类中重写以自定义
	 *｛@link DefaultListableBeanFactory｝的设置。
	 *@param beanFactory为该上下文新建的bean工厂
	 *@请参阅DefaultListableBeanFactory#setAllowBeanDefinitionOverrideing
	 *@见DefaultListableBeanFactory#setAllowCircularReferences
	 *@see DefaultListableBeanFactory#setAllowRawInjectionDessiteWrapping
	 *@见DefaultListableBeanFactory#setAllowEagleClassLoading
	 */
	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

	/**
	 * Load bean definitions into the given bean factory, typically through
	 * delegating to one or more bean definition readers.
	 * @param beanFactory the bean factory to load bean definitions into
	 * @throws BeansException if parsing of the bean definitions failed
	 * @throws IOException if loading of bean definition files failed
	 * @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
	 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
	 */
	/**
	 *将bean定义加载到给定的bean工厂中，通常通过
	 *委托给一个或多个bean定义读取器。
	 *@param beanFactory将bean定义加载到的bean工厂
	 *如果解析bean定义失败，则@throws BeansException
	 *如果加载bean定义文件失败，@throws IOException
	 *@请参阅org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
	 *@参见org.springframework.beans.factory.xml.XmlBeanDefinitionReader
	 */
	protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
			throws BeansException, IOException;

}
